﻿/*************************************************
Author: will
Date: 8/24/2012
Description:
Notes: 
*************************************************/

#ifndef __CBattleRules_h__
#define __CBattleRules_h__

#include "CBattleMap.h"
#include "CBattleRoundCtrl.h"
#include "../skill/CSkill.h"
#include "../skill/CSkillAffect.h"
#include "../maindef.h"

class CBattleRole;
class CBattleRules;

class CBattleSkillTarget
{
public:
    CBattleSkillTarget()
    {
        Clear();
    }

    CBattleSkillTarget(int iID)
    {
        Clear();
        _iID = iID;
    }

    void Clear()
    {
        _bHitted = false;
        _bIsBlock = false;
        _iID = -1;
        _iHitBackDistance = 0;
        _iPullDistance = 0;
    }

    virtual ~CBattleSkillTarget() 
    {
    }

    int GetID() const {return _iID;}

    bool IsHitted() {return _bHitted;}
    void SetHitted() {_bHitted = true;}
    void SetNotHitted() {_bHitted = false;}

    bool IsBlock() {return _bIsBlock;}
    void SetBlock() {_bIsBlock = true;}
    void SetNotBlock() {_bIsBlock = false;}

    void SetHitBackDistance(int iDistance) {_iHitBackDistance = iDistance;};
    void SetPullDistance(int iDistance) {_iPullDistance = iDistance;};
    int GetHitBackDistance() const {return _iHitBackDistance;}
    int GetPullDistance()const {return _iPullDistance;}

    void DumpSkillTargetInfo();

private:
    bool          _bHitted;             //命中
    bool          _bIsBlock;            //格挡
    int           _iID;                 //个体ID
    int           _iHitBackDistance;    //击飞距离
    int           _iPullDistance;       //拖拽距离
};

class CBattleSpecialTarget
{
public:
    CBattleSpecialTarget()
    {
        Clear();
    }

    void Clear()
    {
        _iNowTargetID = -1;
        _iNowAttackID = -1;
        _iNowKillerID = -1;
        _iNowDeaderID = -1;
        _iPreSkillSrcID = -1;
    }

    virtual ~CBattleSpecialTarget() 
    {
    }

    int GetNowTarget() const {return _iNowTargetID;}
    int GetNowAttack() const {return _iNowAttackID;}
    int GetNowKiller() const {return _iNowKillerID;}
    int GetNowDeader() const {return _iNowDeaderID;}
    int GetPreSkillSrcID() const {return _iPreSkillSrcID;}

    void SetNowTarget(int iNowTargetID) {_iNowTargetID = iNowTargetID;}
    void SetNowAttack(int iNowAttackID) {_iNowAttackID = iNowAttackID;}
    void SetNowKiller(int iNowKillerID) {_iNowKillerID = iNowKillerID;}
    void SetNowDeader(int iNowDeaderID) {_iNowDeaderID = iNowDeaderID;}
    void SetPreSkillSrcID(int iRoleID) {_iPreSkillSrcID = iRoleID;}

private:
    int         _iNowTargetID;      //当前攻击敌人
    int         _iNowAttackID;      //当前攻击者
    int         _iNowKillerID;      //当前杀人者
    int         _iNowDeaderID;      //当前死亡者
    int         _iPreSkillSrcID;    //预执行技能施法者ID
};

class CBattleSkillCastEffect
{
    friend class CBattleVideo;
    friend class CBattleRules;
public:
    CBattleSkillCastEffect() 
    {
        Clear();
    }
    void Clear()
    {
        _chTargetType = 0;
        _chTargetFromPos = 0;
        _chTargetEndPos = 0;
        _astTargets.Clear();
    }

    virtual ~CBattleSkillCastEffect() 
    {
    }

    bool IsHitted() 
    {
        for (int i = 0; i < _astTargets.Size(); ++i)
        {
            if (_astTargets[i].IsHitted())
            {
                return true;
            }
        }
        return false;
    }

    bool IsBlock() 
    {
        for (int i = 0; i < _astTargets.Size(); ++i)
        {
            if (_astTargets[i].IsBlock())
            {
                return true;
            }
        }
        return false;
    }

    bool IsToEnemy() { return _stSkillAffect.IsToEnemy();}

    void DumpSkillCastEffectInfo();

private:
    char                _chTargetType;
    char                _chTargetFromPos;
    char                _chTargetEndPos;
    CSkillAffect        _stSkillAffect;
    CTLib::CTArray<CBattleSkillTarget, MAX_SKILL_TARGET_COUNT> _astTargets;
};

class CBattleInfoCount
{
public:
    CBattleInfoCount() 
    {
        Clear();
    }

    void Clear()
    {
        _iLeftTurnTimes = 0;
        _iRightTurnTimes = 0;
    }

    virtual ~CBattleInfoCount() 
    {
    }

    int GetLeftTurnTimes()const{return _iLeftTurnTimes;}
    int GetRightTurnTimes()const{return _iRightTurnTimes;}

    void SetLeftTurnTimes(int iLeftTurnTimes)
    {
        _iLeftTurnTimes = iLeftTurnTimes;
    }
    void SetRightTurnTimes(int iRightTurnTimes)
    {
        _iRightTurnTimes = iRightTurnTimes;
    }

private:
    int     _iLeftTurnTimes;    //左方队伍出手次数
    int     _iRightTurnTimes;   //右方队伍出手次数
};

class CBattleReviseUnit
{
public:
    CBattleReviseUnit() 
    {
        Clear();
    }

    void Clear()
    {
        _iAddNum = 0;
        _iTargetID = 0;
        _uiEffectID = 0;
    }

    virtual ~CBattleReviseUnit() 
    {
    }

    int GetAddNum() const {return _iAddNum;}
    int GetTargetID() const {return _iTargetID;}
    unsigned int GetEffectID() const {return _uiEffectID;}

    void SetAddNum(int iAddNum){_iAddNum = iAddNum;}
    void SetTargetID(int iVal){_iTargetID = iVal;}
    void SetEffectID(unsigned int uiEffectID){_uiEffectID = uiEffectID;}

private:
    int                 _iAddNum;
    int                 _iTargetID;
    unsigned int        _uiEffectID;
};

class CBattleReviseAtk
{
public:
    CBattleReviseAtk() 
    {
        Clear();
    }

    void Clear()
    {
        _astReviseList.Clear();
    }

    virtual ~CBattleReviseAtk() 
    {
    }

    int GetReviseUnitSize() const {return _astReviseList.Size();}

    CBattleReviseUnit& GetReviseUnit(int iIndex){return _astReviseList[iIndex];}

    void AddReviseUnit(CBattleReviseUnit& stUnit)
    {
        _astReviseList.AddOneItem(stUnit);
    }

private:
    CTLib::CTArray<CBattleReviseUnit, MAX_BATTLE_REVISE_ATTACK> _astReviseList;
};

class CStatusObj;
class CBattleAction;
class CBattleRole;
class CBattleBuff;
class CBattleRules
{
public:
    enum BATTLE_ROLE_MOVE_TYPE
    {
        BATTLE_ROLE_MOVE_LEFT_RECORD,
        BATTLE_ROLE_MOVE_RIGHT_RECORD,
        BATTLE_ROLE_MOVE_LEFT_NO_RECORD,
        BATTLE_ROLE_MOVE_RIGHT_NO_RECORD,
    };
    enum BATTLE_RULE_STAT_TYPE
    {
        BATTLE_RULE_STAT_PREPARE        = 0,    //战斗准备阶段
        BATTLE_RULE_STAT_PRE_SKILL      = 1,    //预执行技能阶段
        BATTLE_RULE_STAT_SKILL_TARGET   = 2,    //技能和目标阶段
        BATTLE_RULE_STAT_MAIN_DO        = 3,    //主目标计算阶段
        BATTLE_RULE_STAT_MINOR_DO       = 4,    //辅目标计算阶段
        BATTLE_RULE_STAT_HIT_BACK       = 5,    //目标反击计算阶段
        BATTLE_RULE_STAT_FALL_BACK      = 6,    //目标撤退计算阶段
        BATTLE_RULE_STAT_FINISH         = 7,    //战斗结束阶段
    };

    CBattleRules() 
    {
    }

    virtual ~CBattleRules() 
    {
    }

    int CheckEnd(bool& bIsEnd, int& iResult);

    int DealAtBattleBegin();
    int DealAtTurnBegin();

    //状态操作
    int GetRuleStat()const{return _iRuleStat;}
    void SetRuleStat(int iRuleStat){_iRuleStat = iRuleStat;}

    void InitBattleInfoCount(){_stBattleInfoCount.Clear();}
    int GetLeftTurnTimes()const{return _stBattleInfoCount.GetLeftTurnTimes();}
    int GetRightTurnTimes()const{return _stBattleInfoCount.GetRightTurnTimes();}
    void AddBattleTurnTimes(bool bIsLeft);

    //攻击技能操作
    int GetSkillType()const{return _iSkillType;}
    void SetSkillType(int iSkillType){_iSkillType = iSkillType;}

    int64& GetAtkValue() {return _i64AtkValue;}

    //开始动作
    int GetTurn(int iRoleID);
    
    //行动前BUFF结算
    int CheckBuffBeforeTurn(CBattleRole& stBattleRole);

    //检查是否可以行动
    int CheckCanDoTurn(CBattleRole& stBattleRole);

    //检查技能目标数量
    int GetSkillTargetMaxNum(int& iCount, CSkill& stSkill);

    //选择技能和目标
    int ChooseSkillAndGetTarget(CBattleRole& stBattleRole);

    int FindTargets(CBattleRole& stBattleRole, CSkill& stSkill);

    //主目标选择流程(在地图上找)
    int MainTargetChoose(CBattleRole& stBattleRole,
            CBattleSkillCastEffect& stCastEffect, bool bMove);

    //主目标挑选流程(从找出的范围上选)
    int MainTargetSelect(CBattleRole& stBattleRole,
            CBattleSkillCastEffect& stCastEffect,
            MAP_GRID_MULTI& stMapGridMulti);
        
    //状态目标选择流程(在地图或目标列表中找)
    int StatusTargetChoose(CBattleRole& stBattleRole,
            CSkillAffect& stSkillAffect, MAP_GRID_MULTI& stMapGridMulti);

    bool IsFindMainTarget()
    {
        return _stSkillCastFirstEffect._astTargets.Size() > 0;
    }
    bool IsFindMinorTarget()
    {
        return _stSkillCastSecondEffect._astTargets.Size() > 0;
    }

    //获取波及目标
    int GetMinorOneselfInvoTarget(CBattleRole& stRole, CSkill& stSkill);
    int GetMinorDistanInvoTarget(CBattleRole& stRole, CSkill& stSkill);
    int GetMinorCentreInvoTarget(CBattleRole& stRole, CSkill& stSkill);
    int GetMinorBackInvoTarget(CBattleRole& stRole, CSkill& stSkill);
    int GetMinorMainInvoTarget(CBattleRole& stRole, CSkill& stSkill);

    int GetGroupTarget(CBattleRole& stRole, CSkill& stSkill, bool bToMainTarget);

    int CastSkill(CBattleRole& stRole, CSkill& stSkill, int iMainTargetID);

    int RoleMoveTo(CBattleRole& stRole, int iDstGrid, bool bNeedRecord);

    int SkillPreEffectDataCalc(int& iPreData, int iBase, CSkillEffect& stSkillEffect, int iMulti = 1);
    int SkillPreEffectData(CBattleRole& stRole, bool bIsFirst, CSkillEffect& stSkillEffect);
    int CastSkillPreEffect(CBattleRole& stRole, bool bIsFirst);
    int CastSkillEffectAttr(CBattleRole& stRole);

    int CastSkillEffect(CBattleRole& stRole, CSkill& stSkill);

    //检查命中
    int CastSkillEffectHitRateCheck(CBattleRole& stRole, CBattleSkillCastEffect& stSkillCastEffect, bool bIsFirst);

    //检查格档
    int CastSkillEffectBlockCheck(CBattleRole& stRole, CBattleSkillCastEffect& stSkillCastEffect, bool bIsFirst);

    //检查击飞
    int CastSkillEffectHitBackCheck(CBattleRole& stRole, CBattleSkillCastEffect& stSkillCastEffect);

    //检查拉过来
    int CastSkillEffectPullCheck(CBattleRole& stRole, CBattleSkillCastEffect& stSkillCastEffect);

    int GetRelation(CBattleRole& stBattleRole, CBattleRole& stBattleTarget);

    int RolePreSkill(CBattleRole& stBattleRole);

    int RoleExecSkill(CBattleRole& stBattleRole, CSkill& stSkill);

    int BattleReviseInit(CBattleRole& stBattleRole);

    void AddReviseUnit(CBattleReviseUnit& stUnit)
    {
        _stBattleReviseAtk.AddReviseUnit(stUnit);
    }

    int ReviseAttackValue(CBattleRole& stBattleRole,
            CBattleRole& stBattleTarget);

    int CalculateSkillEffectHP(CBattleRole& stBattleRole,
        CBattleRole& stBattleTarget, CSkillEffect& stSkillEffect, bool bIsFirst,
        int& iChangeHP);

    int CastSkillEffectOnRoleOneEffect(CBattleRole& stBattleRole,
        CBattleRole& stBattleTarget, CPlayerAttr& stBaseAttr,
        CPlayerAttr& stBattleAttr, CPlayerAttr& stTurnAttr,
        CSkillEffect& stSkillEffect, CStatusObj& stStatusObj, int iAuxAddNum,
        int& iBloodChg, bool bChangeHP, bool bIsFirst);

    int CastSkillEffectOnRole(CBattleRole& stBattleRole,
        CBattleRole& stBattleTarget, CSkillAffect& stSkillAffect,
        CStatusObj& stStatusObj, int iAuxAddNum, int& iBloodChg, bool bChangeHP,
        bool bIsFirst);

    int StatusSkillEffect(CBattleRole& stBattleRole,
        CBattleRole& stBattleTarget, CSkillAffect& stSkillAffect,
        CStatusObj& stStatusObj, int iAuxAddNum);

    //战斗伤害计算2。参照文档(第2次结算(伤害的计算、几率事件的计算))
    int SkillEffect2(CBattleRole& stRole, CSkill& stSkill, CBattleSkillCastEffect& stSkillCastEffect, bool bIsFirst);

    //战斗伤害计算3。参照文档(反击)
    int SkillEffect3(CBattleRole& stRole, CSkill& stSkill, CBattleSkillCastEffect& stSkillCastEffect);

    //战斗伤害计算4。目标撤退
    int SkillEffect4(CBattleRole& stRole, CSkill& stSkill, CBattleSkillCastEffect& stSkillCastEffect);

    int GetSkillRandom() const {return _iSkillRandom;}
    void ClearSkillRandom(){_iSkillRandom = -1;}
    void SetSkillRandom(int iSkillRandom){_iSkillRandom = iSkillRandom;}

    int GetNowTarget() const {return _stSpecialTarget.GetNowTarget();}
    int GetNowAttack() const {return _stSpecialTarget.GetNowAttack();}
    int GetNowKiller() const {return _stSpecialTarget.GetNowKiller();}
    int GetNowDeader() const {return _stSpecialTarget.GetNowDeader();}
    int GetPreSkillSrcID() const {return _stSpecialTarget.GetPreSkillSrcID();}

    void SetNowTarget(int iNowTargetID)
    {
        _stSpecialTarget.SetNowTarget(iNowTargetID);
        CT_BATTLE(("设置当前目标(%d)",iNowTargetID));
    }
    void SetNowAttack(int iNowAttackID)
    {
        _stSpecialTarget.SetNowAttack(iNowAttackID);
        CT_BATTLE(("设置当前攻击者(%d)",iNowAttackID));
    }
    void SetNowKiller(int iNowKillerID)
    {
        _stSpecialTarget.SetNowKiller(iNowKillerID);
        CT_BATTLE(("设置当前杀人者(%d)",iNowKillerID));
    }
    void SetNowDeader(int iNowDeaderID)
    {
        _stSpecialTarget.SetNowDeader(iNowDeaderID);
    }
    void SetPreSkillSrcID(int iRoleID)
    {
        _stSpecialTarget.SetPreSkillSrcID(iRoleID);
    }

    void ClearSkillDead(){_aiSkillDead.Clear();}
    void AddSkillDead(int iVal){_aiSkillDead.AddOneItem(iVal);}
    int GetSkillDeadSize()const{return _aiSkillDead.Size();}
    int GetSkillDead(int iIndex){return _aiSkillDead[iIndex];}
    void VideoAllSkillRoleDead();

    void DumpRoleAndTargetInfo(CBattleRole& stRole);
    void DumpRulesInfo();

private:
    bool        _bTurnOver;
    bool        _bTriggerDeadKill;
    int         _iRuleStat;
    int         _iSkillType;
    int         _iSkillRandom;
    int64       _i64AtkValue;
    CSkill      _stCastSkill;
    CTLib::CTArray<int, MAX_BATTLE_ROLES> _aiSkillDead;
    CBattleInfoCount            _stBattleInfoCount;
    CBattleReviseAtk            _stBattleReviseAtk;
    CBattleSpecialTarget        _stSpecialTarget;
    CBattleSkillCastEffect      _stSkillCastFirstEffect;
    CBattleSkillCastEffect      _stSkillCastSecondEffect;
};

#endif // __CBattleRules_h__

